// 单位
import KPlayer from '@kernel/util/player'
import {KUnitCommand} from '@kernel/constant/command'
import AbstractData from '@kernel/interfaces/AbstractData'
import Cache from '@kernel/util/cache'

const cache = new Cache()

export default class KUnit extends AbstractData {
  public handle: Unit;

  constructor(unit: Unit) {
    super()
    this.handle = unit
  }

  /**
   * 创建单位
   * @param player
   * @param typeId
   * @param point
   * @param angle
   */
  static create(player: KPlayer, typeId: number, point: Vector3, angle: number = 0) {
    const unit = gameapi.create_unit(typeId, point, Fix32(angle), player.handle)
    const handle = new KUnit(unit)
    cache.set('unit:' + handle.id, handle)
    return handle
  }

  /**
   * 根据单位id获取实例
   * @param id
   */
  static fromId(id: number) {
    return cache.get('unit:' + id, () => {
      const unit = gameapi.get_unit_by_id(id)
      return new KUnit(unit)
    })
  }

  /**
   * 根据单位handle获取实例
   * @param unit
   */
  static fromHandle(unit: Unit) {
    return cache.get('unit:' + unit.api_get_id(), () => {
      return new KUnit(unit)
    })
  }

  /**
   * 单位id
   */
  get id(): number {
    return <number>this.handle.api_get_id()
  }

  /**
   * 单位名称
   */
  get name(): string {
    return <string>this.handle.api_get_name()
  }

  /**
   * 单位名称
   */
  set name(val: string) {
    this.handle.api_set_name(val)
  }

  /**
   * 所属玩家
   */
  get owner(): KPlayer {
    return KPlayer.fromId(this.handle.api_get_role_id())
  }

  /**
   * 复活单位
   * @param point
   */
  revive(point: FVector3) {
    this.handle.api_revive(point)
  }

  /**
   * 设置警戒范围
   * @param range
   */
  setAlarmRange(range: number) {
    this.handle.api_set_unit_alarm_range(range)
  }

  /**
   * 设置取消警戒范围
   * @param range
   */
  setCancelAlarmRange(range: number) {
    this.handle.api_set_unit_cancel_alarm_range(range)
  }

  /**
   * 发布指令
   * @param command
   * @param data
   */
  releaseCommand<Key extends keyof KUnitCommand>(command: Key, data: KUnitCommand[Key]) {
    let cmd: UnitCommand
    switch (command) {
      case 'attackMove':
        cmd = gameapi.create_unit_command_attack_move(data)
        break;
    }
    if (!cmd) {
      return
    }
    this.handle.api_release_command(cmd)
  }
}
